<?php
/**
 * GeryEngine
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this release in the file LICENSE
 *
 * @copyright  Copyright (c) 2007 Arjen Brouwer
 * @license    New BSD License
 * @author     Arjen Brouwer
 */

class GeryBaseType extends GeryType {

	private $methods;
	
	public function __construct() {
		$this->introspect($this);
	}
	
	public function extend($type) {
		$this->introspect($type);
	}
	
	private function introspect($type) {
		
		$class = new ReflectionClass($type);
		
		if (! is_object($type)) {
			$type = $class->newInstance();
		}
		
		if (! $type instanceof GeryType)
			throw new Exception("Cannot extend from a class that not extends from GeryType");
		
		foreach ($class->getMethods() as $method) {

			// skip constructors and non public methods
			if (! $method->isPublic() || $method->isConstructor())
				continue;
				
			// skip methods of the GeryType class
			if ($method->getDeclaringClass()->getName() == __CLASS__)
				continue;
				
			if (is_object($type)) {
				$invoker = new MethodInvoker($method, $type);
			} else {
				$invoker = MethodInvoker::newStatic($method);
			}
			
			$methodName = strtolower($method->getName());
			
			$this->methods[$methodName] = $invoker;
		}
	}

	public function call($methodName, $val, $parameters, RuntimeServices $rs, $lineNumber) {
		
		$this->rs = $rs;
		$this->lineNumber = $lineNumber;
		
		if (array_key_exists($methodName, $this->methods)) 
		{
			return $this->methods[$methodName]->invoke(array($val, $parameters));
		} 
		else 
		{
			$rs->error("Invalid method '$methodName' for type " . get_class($this), $lineNumber);
			return null;
		}
	}
}
?>